## 14. Web Page Remote Monitor Air Quality In smart school era, environment perception and data interconnection are becoming important symbols of its modernization. In this project, with the theme of Remote Monitoring of Air Quality, we will guide you to deeply explore the innovative application of Internet of Things in school monitoring. From now on, let’s protect the school environment with technology, build a smart learning environment with innovation, and jointly explore the infinite possibilities of Internet of Things in education! #### Principle 1. Data collection ENS160 sensor → ESP32 (via I2C) 2. Data transmission ESP32 → Router → Mobile phone/Computer 3. Data display Browser request → Server response → Update web page #### Code Flow ```mermaid flowchart TD A[Initialization] --> B[Network connection] B --> C[Server starts] C --> D{Request processing} D --> E[Web page] D --> F[Sensor data] E --> G[Real-time monitoring display] F --> G G --> H[Application completed] ``` #### Test Code ```c++ #include #include #include #include // Replace with your WiFi name and passwords const char* ssid = "YourWiFiSSID"; const char* password = "YourWiFiPassword"; WebServer server(80); // Create a Web server object on port 80 DFRobot_ENS160_I2C ens160(&Wire, 0x53); // Create an ENS160 sensor object void setup() { Serial.begin(115200); Wire.begin(); // Initialize the I2C bus // Initialize the ENS160 sensor while(ens160.begin() != 0) { Serial.println("ENS160 sensor initialization failed, please check connection!"); delay(1000); } Serial.println("ENS160 sensor initialized successfully!"); // Set work mode ens160.setPWRMode(ENS160_STANDARD_MODE); // Set the measurement environment data (temperature 25°C and humidity 50%RH as default values) ens160.setTempAndHum(25.0, 50.0); // connect to WiFi WiFi.begin(ssid, password); Serial.print("Connecting to WiFi..."); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); // Set server routing server.on("/", handleRoot); // Root path server.on("/data", handleData); // Data API path // Start the server server.begin(); Serial.println("HTTP server started"); } void loop() { server.handleClient(); // Handle client requests // Update sensor data static unsigned long lastUpdate = 0; if (millis() - lastUpdate >= 1000) { // Updated once per second lastUpdate = millis(); } } // Handle root path requests void handleRoot() { String html = R"=====( ENS160 Air Quality Sensor

ENS160 Air Quality Sensor

Air Quality Index (AQI)
--
--
1-5 (1=Excellent, 5=Unhealthy)
TVOC Concentration
-- ppb
CO2 Equivalent
-- ppm
Last update: --
)====="; server.send(200, "text/html", html); } // Handle data API requests void handleData() { // Obtain the data from the ENS160 sensor uint8_t aqi = ens160.getAQI(); uint16_t tvoc = ens160.getTVOC(); uint16_t eco2 = ens160.getECO2(); // Create a JSON response String json = "{"; json += "\"aqi\":" + String(aqi) + ","; json += "\"tvoc\":" + String(tvoc) + ","; json += "\"eco2\":" + String(eco2); json += "}"; server.send(200, "application/json", json); } ``` #### Code Explanation **Here covers extracurricular knowledge of HTML, CSS, and JS, so we only provide a brief introduction.** **1.Hardware initialization** ```c++ Wire.begin(); // Initialize the I2C bus // Initialize the ENS160 sensor while(ens160.begin() != 0) { Serial.println("ENS160 sensor initialization failed, please check connection!"); delay(1000); } Serial.println("ENS160 sensor initialized successfully!"); ``` - Communicate with the sensor via the I2C protocol. If the sensor is not connected, the program will keep detecting.
**2. Network service** **WiFi connectioin** ```c++ WiFi.begin(ssid, password); Serial.print("CWiFi..."); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi is connected"); Serial.print("IP: "); Serial.println(WiFi.localIP()); ``` - After connection, the serial port will print the local area network IP of the ESP32 **Server initialization** ```c++ WebServer server(80); // Create an HTTP server on port 80 // Route registration server.on("/", handleRoot); // Root path → Return to HTML page server.on("/data", handleData); // Data path → Return JSON data server.begin(); // Start the server Serial.println("HTTP server started"); ``` - `/` : Return the HTML of the visual web page - `/data` : Return sensor data in JSON format **Request processing loop** ```c++ void loop() { server.handleClient(); // Handle incoming client requests } ```
**3. Data processing** **Data API processing function** ```c++ void handleData() { // 1. Sensor data acquisition uint8_t aqi = ens160.getAQI(); // Air Quality index uint16_t tvoc = ens160.getTVOC(); // Volatile organic compounds uint16_t eco2 = ens160.getECO2(); // Equivalent carbon dioxide // 2. JSON data construction String json = "{"; json += "\"aqi\":" + String(aqi) + ","; json += "\"tvoc\":" + String(tvoc) + ","; json += "\"eco2\":" + String(eco2); json += "}"; // 3. HTTP response sending server.send(200, "application/json", json); // Status code 200, in JSON format } ``` - Data processing flow Sensor reading → Data formatting → JSON construction → HTTP response
**4. Dynamic update** ```javascript function refreshData() { fetch('/data') // Initiate an API request .then(response => response.json()) // Parse the JSON response .then(data => { // DOM update document.getElementById('aqi-value').textContent = data.aqi; document.getElementById('tvoc-value').textContent = data.tvoc; document.getElementById('eco2-value').textContent = data.eco2; // Status visualization update const aqiStatus = getAqiStatus(data.aqi); aqiElement.textContent = aqiStatus.text; aqiElement.style.backgroundColor = aqiStatus.color; // Timestamp update document.getElementById('last-updated').textContent = `Last update: ${new Date().toLocaleTimeString()}`; }) } // Timed automatic update setInterval(refreshData, 5000); // Updated every 5 seconds // Update the page loading immediately window.onload = refreshData; // Manual update button ``` #### Test Result 1. After uploading the code, open the serial monitor and set the baud rate to 115200. You can see the printed IP information: ![1102](../../img/1102.png) 2. Enter this IP address in the browser of your mobile phone or computer to access the air quality monitoring page. - Automatic update: Data is obtained immediately when the page is opened, and the page automatically refreshes with data updated every 5 seconds. - Manual update: Click the refresh button to update immediately. New data will be displayed immediately after the operation. - Visual feedback: The status box dynamically changes color based on the AQI value, and the timestamp shows the last update time. Note: Make sure your mobile phone/computer and ESP32 are connected to the same WiFi. ![1401](../../img/1401.png) #### FAQ 1. If nothing is printed on the serial monitor, please press the reset button on the board. ![RESET](../../img/RESET.png) 2. If the ESP32 has not been able to obtain an IP address, it is usually because the WiFi connection has failed. Solutions: - Make sure that the WiFi name and password in the code have been replaced with yours. - Make sure your WiFi network is 2.4GHz. ESP32 does not support 5GHz WiFi. 3. If there is no page when entering the IP address, - Make sure the IP address is entered correctly. - Check whether your mobile phone/computer is on the same network as the ESP32.